# @File: get_case_data.py
# -*- coding: utf-8 -*-
# __author:"super"
# @time:2025/9/18 19:02

from abc import ABC, abstractmethod
from typing import Optional
from tools.log import Logger
from tools.general_tool import CaseFilePath
import json
import openpyxl

logger = Logger().logger


class CaseReader(ABC):
    """抽象读取器接口
    """

    @abstractmethod
    def get_case_data(self, **kwargs) -> list[dict]:
        ...

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass


class XlsxCaseReader(CaseReader):
    """Excel测试用例读取器
    """

    def __init__(self, file_name: str):
        """
        Args:
            file_name: 用例文件名称（自动解析完整路径）
        """
        self.file_path = CaseFilePath().get_case_file(file_name)  # 获取物理路径
        # 修改:
        self.work_book = openpyxl.load_workbook(str(self.file_path), data_only=True)  # data_only=True 获取计算后的值

    def get_case_data(self, sheet_name: str) -> list[dict]:
        """将Excel工作表解析为结构化字典列表

        Args:
            sheet_name: 目标工作表名称，支持中文名称

        Returns:
            按行解析的字典列表，每个字典对应一行数据，包含：
            - 列头字段 -> 单元格值
            - metadata: 原始数据信息（如行号）
        """
        # 修改:
        worksheet = self.work_book[sheet_name]  # 获取指定sheet
        column_headers = [cell.value for cell in worksheet[1]]  # 提取首行列头
        row_count, column_count = worksheet.max_row, worksheet.max_column

        parsed_data = []
        for row_idx in range(2, row_count + 1):  # openpyxl从1开始计数，首行是列头
            try:
                row_values = [cell.value for cell in worksheet[row_idx]]

                # 检查是否为空行
                if not any(val for val in row_values if val is not None and str(val).strip()):
                    continue  # 跳过空行

                row_dict = self._process_row_data(row_values, column_headers, column_count)

                # 检查处理后的字典是否有效
                if not row_dict:
                    continue  # 跳过结果为空的行

                row_dict["metadata"] = {"source_row": row_idx}
                parsed_data.append(row_dict)
            except Exception as e:
                logger.error(f"第{row_idx}行数据解析失败: {str(e)}")
                continue
        return parsed_data

    def _process_row_data(self, row_values: list, headers: list, column_count: int) -> dict:
        """处理单行数据转换
        """
        row_dict = {}
        for col_idx in range(min(len(headers), len(row_values))):  # 防止索引越界
            header = headers[col_idx]
            raw_value = row_values[col_idx]
            if header:  # 确保列头不为空
                row_dict[header] = self._type_cast_cell_value(raw_value)
        return row_dict

    @staticmethod
    def _type_cast_cell_value(raw_value) -> any:
        """转换单元格值类型"""
        # None值处理
        if raw_value is None:
            return ""

            # JSON处理优先（增强检测）
        if isinstance(raw_value, str):
            raw_value = raw_value.strip()
            if (raw_value.startswith('{') and raw_value.endswith('}')) or \
                    (raw_value.startswith('[') and raw_value.endswith(']')):
                try:
                    return json.loads(raw_value)
                except json.JSONDecodeError:
                    logger.warning(f"JSON解析失败，保留原始值: {raw_value}")

                    # 数值类型处理
        if isinstance(raw_value, (int, float)):
            return int(raw_value) if raw_value == int(raw_value) else raw_value

            # 默认字符串处理
        return str(raw_value).strip() if raw_value else ""


class JsonCaseReader(CaseReader):
    """JSON测试用例读取器
    """

    def __init__(self, file_name: str):
        """
        Args:
            file_name: JSON文件名称（自动解析路径）
        """
        self.file_path = CaseFilePath().get_json_case_file(file_name)

    def get_case_data(self, **kwargs) -> list[dict]:
        """直接加载JSON数组
        """
        with open(str(self.file_path), 'r', encoding='utf-8') as f:
            return json.load(f)


class YmlCaseReader(CaseReader):
    """YAML测试用例读取器（待实现）
    """

    def __init__(self, file_name):
        pass

    def get_case_data(self, **kwargs):
        pass


class CaseReaderFactory:
    """
    读取器工厂
    """

    @staticmethod
    def create_reader(file_type: str, file_name: str) -> CaseReader:
        """创建对应类型的读取器实例
        Args:
            file_type: 文件类型标识（不区分大小写）
            file_name: 目标文件名称
        Returns:
            具体CaseReader子类实例
        """
        readers = {
            'excel': XlsxCaseReader,  # Excel读取器
            'json': JsonCaseReader  # JSON读取器
        }
        reader_class = readers.get(file_type.lower())
        if not reader_class:
            raise ValueError(f"暂不支持的文件格式: {file_type}")
        return reader_class(file_name)


class GenerateCaseData:
    """
    测试用例读取生成器 - 可迭代对象版本
    """

    def __init__(self, file_name: str, start=None, stop=None,
                 file_type='excel', **reader_params):
        self.file_name = file_name
        self.file_type = file_type
        self.start = start
        self.stop = stop
        self.reader_params = reader_params

    def __iter__(self):
        """每次调用返回全新的迭代器"""
        reader = CaseReaderFactory.create_reader(self.file_type, self.file_name)
        with reader as r:
            data_slice = r.get_case_data(**self.reader_params)[self.start:self.stop]
            for item in data_slice:
                yield item


class ExtractSubstring:
    """
    提取字符串中的数字
    """

    @staticmethod
    def extract_substring(original_str: str, start_index: int, length: int) -> Optional[str]:
        """
            从字符串中动态截取子串

            :param original_str: 原始字符串（如日期字符串）
            :param start_index: 起始索引（从0开始，例如“第4位”对应索引3）
            :param length: 要截取的长度
            :return: 截取后的子串；若输入无效则返回 None
            """
        try:
            # 验证输入有效性
            if not isinstance(original_str, str):
                raise TypeError(f"原始值必须是字符串，实际类型：{type(original_str)}")
            if not isinstance(start_index, int) or start_index < 0:
                raise ValueError(f"起始索引必须是非负整数，实际值：{start_index}")
            if not isinstance(length, int) or length <= 0:
                raise ValueError(f"截取长度必须是正整数，实际值：{length}")
            # 计算结束索引（起始索引 + 长度）
            end_index = start_index + length

            # 检查是否越界
            if end_index > len(original_str):
                raise IndexError(f"截取范围越界！字符串长度为 {len(original_str)}，请求截取 {start_index} 到 {end_index}")
            # 执行截取
            return original_str[start_index:end_index]

        except Exception as e:
            print(f"截取失败：{e}")
            return None

    @staticmethod
    def sku_name_parse(sku_full_name: str) -> tuple:
        """
        解析SKU全称，提取SKU编码和显示名称
        
        示例输入:
        - "test sku001/sku39665284" -> ("sku39665284", "sku39665284(test sku001)")
        - "sku39665284(test sku001)" -> ("sku39665284", "sku39665284(test sku001)")
        
        :param sku_full_name: SKU完整名称
        :return: (sku_code, sku_display) 元组
        """
        try:
            if not sku_full_name or not isinstance(sku_full_name, str):
                raise ValueError(f"SKU名称无效: {sku_full_name}")
            
            # 情况1: "test sku001/sku39665284" 格式
            if '/' in sku_full_name:
                parts = sku_full_name.split('/')
                sku_code = parts[1].strip()  # sku39665284
                sku_name = parts[0].strip()  # test sku001
                sku_display = f"{sku_code}({sku_name})"  # sku39665284(test sku001)
            # 情况2: "sku39665284(test sku001)" 格式
            elif '(' in sku_full_name:
                sku_code = sku_full_name.split('(')[0].strip()  # sku39665284
                sku_display = sku_full_name  # 保持原样
            else:
                # 只有编码，没有名称
                sku_code = sku_full_name.strip()
                sku_display = sku_code
            
            return sku_code, sku_display
            
        except Exception as e:
            print(f"SKU解析失败: {e}")
            return sku_full_name, sku_full_name  # 降级处理

    def sku_select(self):
        """
        test sku001/sku39665284
        sku39665284(test sku001)

        :return:
        """



if __name__ == '__main__':
    # g = GenerateCaseData(file_name='接口测试用例-定制品图搜', sheet_name='定制品图搜')
    g = GenerateCaseData(file_name='入库_ASN列表', sheet_name='ASN列表_搜索数据')
    for item in g:
        print(item)
        arrival_time = item.get('预计到货时间')
        print("预计到货时间", arrival_time)
        # mm_dd = arrival_time[4:10]
        mm_dd = ExtractSubstring.extract_substring(arrival_time, 4, 6)
        print("mm_dd", mm_dd)
        # esti_arrival_time = g.get('预计到货时间')
